package com.wan.thread.actor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.LongAdder;

public class ActorThread {
    public static final int tooLong = 350; //超过ms的处理时长
    public static final int warnSize = 300;

    private static final Logger logger = LoggerFactory.getLogger(ActorThread.class);
    private final String name;
    private final BlockingQueue<Runnable> queue;
    private final AtomicBoolean open = new AtomicBoolean(true);

    private final LongAdder successTotal = new LongAdder();
    private final LongAdder failTotal = new LongAdder();

    public ActorThread(String name) {
        this.name = name;
        this.queue = new LinkedTransferQueue<>();
        new Thread(this::run, name).start();
    }


    public void run(){
        while (open.get()) {
            try {
                Runnable actor = queue.take();
                long start = System.currentTimeMillis();
                actor.run();
                long cost = System.currentTimeMillis() - start;
                if(cost > tooLong){
                    logger.warn("{} 执行时间过长{}ms",name,cost);
                }
                successTotal.increment();
            } catch (Exception e) {
                logger.error("{} 执行出错",name,e);
                failTotal.increment();
            }
        }
    }

    public void addActor(Runnable actor){
        try {
            if(!open.get()){
                return;
            }
            this.queue.put(actor);
            if(getSize() > warnSize){
                logger.warn("{} 堆积任务过多:{}个",name,getSize());
            }
        } catch (Exception e) {
            logger.error("{} 添加任务失败",name,e);
        }
    }


    public int getSize(){
        return queue.size();
    }

    public long getSuccessTotal(){
        return successTotal.longValue();
    }

    public long getFailTotal(){
        return failTotal.longValue();
    }

    public String getName() {
        return name;
    }

    public void shutdown(){
        if(open.compareAndSet(true,false)){
            if(queue.isEmpty()){
                return;
            }
            for (Runnable actor : queue) {
                try {
                    actor.run();
                    successTotal.increment();
                } catch (Exception e) {
                    logger.error("{} shutdown执行出错",name,e);
                    failTotal.increment();
                }
            }
        }
    }

    @Override
    public String toString() {
        String str = "%s:[current: %s,success: %s,fail: %s]";
        return String.format(str,name,getSize(),getSuccessTotal(),getFailTotal());
    }
}
